home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Applications / Python 1.3.3 / Python 133 SRC / Mac / Demo / waste / wed.py < prev    next >
Text File  |  1996-04-19  |  10KB  |  422 lines

  1. # A minimal text editor.
  2. #
  3. # To be done:
  4. # - Functionality: find, etc.
  5.  
  6. from Menu import DrawMenuBar
  7. from FrameWork import *
  8. import Win
  9. import Qd
  10. import Res
  11. import waste
  12. import WASTEconst
  13. import Scrap
  14. import os
  15. import macfs
  16.  
  17. UNDOLABELS = [ # Indexed by WEGetUndoInfo() value
  18.     None, "", "typing", "Cut", "Paste", "Clear", "Drag", "Style"]
  19.     
  20. BIGREGION=Qd.NewRgn()
  21. Qd.SetRectRgn(BIGREGION, -16000, -16000, 16000, 16000)
  22.  
  23. class WasteWindow(ScrolledWindow):
  24.     def open(self, path, name, data):
  25.         self.path = path
  26.         self.name = name
  27.         r = windowbounds(400, 400)
  28.         w = Win.NewWindow(r, name, 1, 0, -1, 1, 0x55555555)
  29.         self.wid = w
  30.         vr = 0, 0, r[2]-r[0]-15, r[3]-r[1]-15
  31.         dr = (0, 0, 10240, 0)
  32.         Qd.SetPort(w)
  33.         Qd.TextFont(4)
  34.         Qd.TextSize(9)
  35.         flags = WASTEconst.weDoAutoScroll | WASTEconst.weDoOutlineHilite | \
  36.             WASTEconst.weDoMonoStyled | WASTEconst.weDoUndo
  37.         self.ted = waste.WENew(dr, vr, flags)
  38.         self.tedtexthandle = Res.Resource(data)
  39.         self.ted.WEUseText(self.tedtexthandle)
  40.         self.ted.WECalText()
  41.         w.DrawGrowIcon()
  42.         self.scrollbars()
  43.         self.changed = 0
  44.         self.do_postopen()
  45.         self.do_activate(1, None)
  46.         
  47.     def do_idle(self, event):
  48.         (what, message, when, where, modifiers) = event
  49.         Qd.SetPort(self.wid)
  50.         self.ted.WEIdle()    
  51.         if self.ted.WEAdjustCursor(where, BIGREGION):
  52.             return
  53.         Qd.SetCursor(Qd.qd.arrow)
  54.         
  55.     def getscrollbarvalues(self):
  56.         dr = self.ted.WEGetDestRect()
  57.         vr = self.ted.WEGetViewRect()
  58.         vx = self.scalebarvalue(dr[0], dr[2], vr[0], vr[2])
  59.         vy = self.scalebarvalue(dr[1], dr[3], vr[1], vr[3])
  60. ##        print dr, vr, vx, vy
  61.         return vx, vy
  62.         
  63.     def scrollbar_callback(self, which, what, value):
  64.         if which == 'y':
  65.             if what == 'set':
  66.                 height = self.ted.WEGetHeight(0, 0x3fffffff)
  67.                 cur = self.getscrollbarvalues()[1]
  68.                 delta = (cur-value)*height/32767
  69.             if what == '-':
  70.                 topline_off,dummy = self.ted.WEGetOffset((1,1))
  71.                 topline_num = self.ted.WEOffsetToLine(topline_off)
  72.                 delta = self.ted.WEGetHeight(topline_num, topline_num+1)
  73.             elif what == '--':
  74.                 delta = (self.ted.WEGetViewRect()[3]-10)
  75.                 if delta <= 0:
  76.                     delta = 10 # Random value
  77.             elif what == '+':
  78.                 # XXXX Wrong: should be bottom line size
  79.                 topline_off,dummy = self.ted.WEGetOffset((1,1))
  80.                 topline_num = self.ted.WEOffsetToLine(topline_off)
  81.                 delta = -self.ted.WEGetHeight(topline_num, topline_num+1)
  82.             elif what == '++':
  83.                 delta = -(self.ted.WEGetViewRect()[3]-10)
  84.                 if delta >= 0:
  85.                     delta = -10
  86.             self.ted.WEScroll(0, delta)
  87. ##            print 'SCROLL Y', delta
  88.         else:
  89.             if what == 'set':
  90.                 return # XXXX
  91.             vr = self.ted.WEGetViewRect()
  92.             winwidth = vr[2]-vr[0]
  93.             if what == '-':
  94.                 delta = winwidth/10
  95.             elif what == '--':
  96.                 delta = winwidth/2
  97.             elif what == '+':
  98.                 delta = -winwidth/10
  99.             elif what == '++':
  100.                 delta = -winwidth/2
  101.             self.ted.WEScroll(delta, 0)
  102.         # Pin the scroll
  103.         l, t, r, b = self.ted.WEGetDestRect()
  104.         vl, vt, vr, vb = self.ted.WEGetViewRect()
  105.         if t > 0 or l > 0:
  106.             dx = dy = 0
  107.             if t > 0: dy = -t
  108.             if l > 0: dx = -l
  109. ##            print 'Extra scroll', dx, dy
  110.             self.ted.WEScroll(dx, dy)
  111.         elif b < vb:
  112. ##            print 'Extra downscroll', b-vb
  113.             self.ted.WEScroll(0, b-vb)
  114.  
  115.         
  116.     def do_activate(self, onoff, evt):
  117. ##        print "ACTIVATE", onoff
  118.         Qd.SetPort(self.wid)
  119.         ScrolledWindow.do_activate(self, onoff, evt)
  120.         if onoff:
  121.             self.ted.WEActivate()
  122.             self.parent.active = self
  123.             self.parent.updatemenubar()
  124.         else:
  125.             self.ted.WEDeactivate()
  126.  
  127.     def do_update(self, wid, event):
  128.         region = wid.GetWindowPort().visRgn
  129.         if Qd.EmptyRgn(region):
  130.             return
  131.         Qd.EraseRgn(region)
  132.         self.ted.WEUpdate(region)
  133.         self.updatescrollbars()
  134.         
  135.     def do_postresize(self, width, height, window):
  136.         l, t, r, b = self.ted.WEGetViewRect()
  137.         vr = (l, t, l+width-15, t+height-15)
  138.         self.ted.WESetViewRect(vr)
  139.         Win.InvalRect(vr)
  140.         ScrolledWindow.do_postresize(self, width, height, window)
  141.         
  142.     def do_contentclick(self, local, modifiers, evt):
  143.         (what, message, when, where, modifiers) = evt
  144.         self.ted.WEClick(local, modifiers, when)
  145.         self.updatescrollbars()
  146.         self.parent.updatemenubar()
  147.  
  148.     def do_char(self, ch, event):
  149.         self.ted.WESelView()
  150.         (what, message, when, where, modifiers) = event
  151.         self.ted.WEKey(ord(ch), modifiers)
  152.         self.changed = 1
  153.         self.updatescrollbars()
  154.         self.parent.updatemenubar()
  155.         
  156.     def close(self):
  157.         if self.changed:
  158.             save = EasyDialogs.AskYesNoCancel('Save window "%s" before closing?'%self.name, 1)
  159.             if save > 0:
  160.                 self.menu_save()
  161.             elif save < 0:
  162.                 return
  163.         if self.parent.active == self:
  164.             self.parent.active = None
  165.         self.parent.updatemenubar()
  166.         del self.ted
  167.         del self.tedtexthandle
  168.         self.do_postclose()
  169.         
  170.     def menu_save(self):
  171.         if not self.path:
  172.             self.menu_save_as()
  173.             return # Will call us recursively
  174. ##        print 'Saving to ', self.path
  175.         dhandle = self.ted.WEGetText()
  176.         data = dhandle.data
  177.         fp = open(self.path, 'wb')  # NOTE: wb, because data has CR for end-of-line
  178.         fp.write(data)
  179.         if data[-1] <> '\r': fp.write('\r')
  180.         fp.close()
  181.         self.changed = 0
  182.         
  183.     def menu_save_as(self):
  184.         fss, ok = macfs.StandardPutFile('Save as:')
  185.         if not ok: return
  186.         self.path = fss.as_pathname()
  187.         self.name = os.path.split(self.path)[-1]
  188.         self.wid.SetWTitle(self.name)
  189.         self.menu_save()
  190.         
  191.     def menu_cut(self):
  192.         self.ted.WESelView()
  193.         self.ted.WECut()
  194.         Scrap.ZeroScrap()
  195.         self.ted.WECut()
  196.         self.updatescrollbars()
  197.         self.parent.updatemenubar()
  198.         self.changed = 1
  199.         
  200.     def menu_copy(self):
  201.         Scrap.ZeroScrap()
  202.         self.ted.WECopy()
  203.         self.updatescrollbars()
  204.         self.parent.updatemenubar()
  205.         
  206.     def menu_paste(self):
  207.         self.ted.WESelView()
  208.         self.ted.WEPaste()
  209.         self.updatescrollbars()
  210.         self.parent.updatemenubar()
  211.         self.changed = 1
  212.         
  213.     def menu_clear(self):
  214.         self.ted.WESelView()
  215.         self.ted.WEDelete()
  216.         self.updatescrollbars()
  217.         self.parent.updatemenubar()
  218.         self.changed = 1
  219.  
  220.     def menu_undo(self):
  221.         self.ted.WEUndo()
  222.         self.updatescrollbars()
  223.         self.parent.updatemenubar()
  224.                 
  225.     def have_selection(self):
  226.         start, stop = self.ted.WEGetSelection()
  227.         return start < stop
  228.         
  229.     def can_paste(self):
  230.         return self.ted.WECanPaste()
  231.         
  232.     def can_undo(self):
  233.         which, redo = self.ted.WEGetUndoInfo()
  234.         which = UNDOLABELS[which]
  235.         if which == None: return None
  236.         if redo:
  237.             return "Redo "+which
  238.         else:
  239.             return "Undo "+which
  240.  
  241. class Wed(Application):
  242.     def __init__(self):
  243.         Application.__init__(self)
  244.         self.num = 0
  245.         self.active = None
  246.         self.updatemenubar()
  247.         
  248.     def makeusermenus(self):
  249.         self.filemenu = m = Menu(self.menubar, "File")
  250.         self.newitem = MenuItem(m, "New window", "N", self.open)
  251.         self.openitem = MenuItem(m, "Open...", "O", self.openfile)
  252.         self.closeitem = MenuItem(m, "Close", "W", self.closewin)
  253.         m.addseparator()
  254.         self.saveitem = MenuItem(m, "Save", "S", self.save)
  255.         self.saveasitem = MenuItem(m, "Save as...", "", self.saveas)
  256.         m.addseparator()
  257.         self.quititem = MenuItem(m, "Quit", "Q", self.quit)
  258.         
  259.         self.editmenu = m = Menu(self.menubar, "Edit")
  260.         self.undoitem = MenuItem(m, "Undo", "Z", self.undo)
  261.         self.cutitem = MenuItem(m, "Cut", "X", self.cut)
  262.         self.copyitem = MenuItem(m, "Copy", "C", self.copy)
  263.         self.pasteitem = MenuItem(m, "Paste", "V", self.paste)
  264.         self.clearitem = MenuItem(m, "Clear", "", self.clear)
  265.         
  266.         # Groups of items enabled together:
  267.         self.windowgroup = [self.closeitem, self.saveitem, self.saveasitem, self.editmenu]
  268.         self.focusgroup = [self.cutitem, self.copyitem, self.clearitem]
  269.         self.windowgroup_on = -1
  270.         self.focusgroup_on = -1
  271.         self.pastegroup_on = -1
  272.         self.undo_label = "never"
  273.         
  274.     def updatemenubar(self):
  275.         changed = 0
  276.         on = (self.active <> None)
  277.         if on <> self.windowgroup_on:
  278.             for m in self.windowgroup:
  279.                 m.enable(on)
  280.             self.windowgroup_on = on
  281.             changed = 1
  282.         if on:
  283.             # only if we have an edit menu
  284.             on = self.active.have_selection()
  285.             if on <> self.focusgroup_on:
  286.                 for m in self.focusgroup:
  287.                     m.enable(on)
  288.                 self.focusgroup_on = on
  289.                 changed = 1
  290.             on = self.active.can_paste()
  291.             if on <> self.pastegroup_on:
  292.                 self.pasteitem.enable(on)
  293.                 self.pastegroup_on = on
  294.                 changed = 1
  295.             on = self.active.can_undo()
  296.             if on <> self.undo_label:
  297.                 if on:
  298.                     self.undoitem.enable(1)
  299.                     self.undoitem.settext(on)
  300.                     self.undo_label = on
  301.                 else:
  302.                     self.undoitem.settext("Nothing to undo")
  303.                     self.undoitem.enable(0)
  304.                 changed = 1
  305.         if changed:
  306.             DrawMenuBar()
  307.  
  308.     #
  309.     # Apple menu
  310.     #
  311.     
  312.     def do_about(self, id, item, window, event):
  313.         EasyDialogs.Message("A simple single-font text editor based on WASTE")
  314.             
  315.     #
  316.     # File menu
  317.     #
  318.  
  319.     def open(self, *args):
  320.         self._open(0)
  321.         
  322.     def openfile(self, *args):
  323.         self._open(1)
  324.  
  325.     def _open(self, askfile):
  326.         if askfile:
  327.             fss, ok = macfs.StandardGetFile('TEXT')
  328.             if not ok:
  329.                 return
  330.             path = fss.as_pathname()
  331.             name = os.path.split(path)[-1]
  332.             try:
  333.                 fp = open(path, 'rb') # NOTE binary, we need cr as end-of-line
  334.                 data = fp.read()
  335.                 fp.close()
  336.             except IOError, arg:
  337.                 EasyDialogs.Message("IOERROR: "+`arg`)
  338.                 return
  339.         else:
  340.             path = None
  341.             name = "Untitled %d"%self.num
  342.             data = ''
  343.         w = WasteWindow(self)
  344.         w.open(path, name, data)
  345.         self.num = self.num + 1
  346.         
  347.     def closewin(self, *args):
  348.         if self.active:
  349.             self.active.close()
  350.         else:
  351.             EasyDialogs.Message("No active window?")
  352.         
  353.     def save(self, *args):
  354.         if self.active:
  355.             self.active.menu_save()
  356.         else:
  357.             EasyDialogs.Message("No active window?")
  358.         
  359.     def saveas(self, *args):
  360.         if self.active:
  361.             self.active.menu_save_as()
  362.         else:
  363.             EasyDialogs.Message("No active window?")
  364.             
  365.         
  366.     def quit(self, *args):
  367.         for w in self._windows.values():
  368.             w.close()
  369.         if self._windows:
  370.             return
  371.         raise self
  372.         
  373.     #
  374.     # Edit menu
  375.     #
  376.     
  377.     def undo(self, *args):
  378.         if self.active:
  379.             self.active.menu_undo()
  380.         else:
  381.             EasyDialogs.Message("No active window?")
  382.         
  383.     def cut(self, *args):
  384.         if self.active:
  385.             self.active.menu_cut()
  386.         else:
  387.             EasyDialogs.Message("No active window?")
  388.         
  389.     def copy(self, *args):
  390.         if self.active:
  391.             self.active.menu_copy()
  392.         else:
  393.             EasyDialogs.Message("No active window?")
  394.         
  395.     def paste(self, *args):
  396.         if self.active:
  397.             self.active.menu_paste()
  398.         else:
  399.             EasyDialogs.Message("No active window?")
  400.  
  401.     def clear(self, *args):
  402.         if self.active:
  403.             self.active.menu_clear()
  404.         else:
  405.             EasyDialogs.Message("No active window?")
  406.         
  407.     #
  408.     # Other stuff
  409.     #    
  410.  
  411.     def idle(self, event):
  412.         if self.active:
  413.             self.active.do_idle(event)
  414.  
  415. def main():
  416.     App = Ped()
  417.     App.mainloop()
  418.     
  419. if __name__ == '__main__':
  420.     main()
  421.     
  422.